/*!
\brief      Used to indicate what is being used to do 
a SQLDriverConnect.
*/
#include <windows.h>
#include <WinNT.h>
#include <sqltypes.h>

// Utility macros
#define is_connected(dbc)    ((dbc)->open_plant.net.vio)


/* max dsn's we can have in odbc sys info - need to get
rid of this limit */
#define OPODBCUTIL_MAX_DSN_NAMES 50

/* Could use DRIVER_NAME but trying to keep dependency
upon driver specific code to a min */
#define OPODBCINST_DRIVER_NAME "openPlant ODBC 3.00 Driver"

#define SAVE_MODE()
#define RESTORE_MODE()

#if defined(WIN32)
#	define _global_free(p) GlobalFree(p)
# define _global_strndup(s, n) strnglobaldup(s, n)
#endif


typedef enum odbc_data_source_connect_t
{
	OPODBCUTIL_DATASOURCE_CONNECT_DRIVER,
	OPODBCUTIL_DATASOURCE_CONNECT_DSN

} odbc_data_source_connect_t;

/*!
\brief      DSN edit mode.

Reason why we have created a odbc_data_source_t.
*/
typedef enum odbc_data_source_mode_t
{
	OPODBCUTIL_DATASOURCE_MODE_DSN_ADD,         /* For ConfigDSN() - ODBC_ADD_DSN.              */
	OPODBCUTIL_DATASOURCE_MODE_DSN_EDIT,        /* For ConfigDSN() - ODBC_CONFIG_DSN.           */
	OPODBCUTIL_DATASOURCE_MODE_DSN_VIEW,        /* For command-line tools to list DSN details.  */
	OPODBCUTIL_DATASOURCE_MODE_DRIVER_CONNECT   /* For SQLDriverConnect().                      */
} odbc_data_source_mode_t;

/*!
\brief      Prompting used during SQLDriverConnect.

Could be a SQLUSMALLINT and then standard
ODBC values such as SQL_DRIVER_PROMPT but there
are worthwhile advantages to creating this type
internally.
*/
typedef enum odbc_data_source_prompt_t
{
	OPODBCUTIL_DATASOURCE_PROMPT_PROMPT,
	OPODBCUTIL_DATASOURCE_PROMPT_COMPLETE, 
	OPODBCUTIL_DATASOURCE_PROMPT_REQUIRED,
	OPODBCUTIL_DATASOURCE_PROMPT_NOPROMPT
} odbc_data_source_prompt_t;

/*!
\internal
\brief      Delimiter type used for an attribute string.

*/  
typedef enum odbc_delim_t
{
	OPODBCUTIL_DELIM_NULL,
	OPODBCUTIL_DELIM_SEMI,
	OPODBCUTIL_DELIM_BOTH
} odbc_delim_t;

/*!
\internal
\brief      Parse state.

These are the different states we can be in while parsing 
an attributes string.
*/  
typedef enum odbc_attr_parse_state_t
{
	OPODBCUTIL_ATTR_PARSE_STATE_NAME_START,   /* looking for start of name  */
	OPODBCUTIL_ATTR_PARSE_STATE_NAME,         /* looking for end of name    */
	OPODBCUTIL_ATTR_PARSE_STATE_EQUAL,        /* looking for equal sign     */
	OPODBCUTIL_ATTR_PARSE_STATE_VALUE_START,  /* looking for start of value */
	OPODBCUTIL_ATTR_PARSE_STATE_VALUE         /* looking for end of value   */
} odbc_attr_parse_state_t;

/*!
Driver fields.

This reflects what we can have in odbcinst.ini.
*/
typedef struct odbc_driver_t
{
	char *name;              /* Friendly name for driver.                (ie "openPlant ODBC 3.51 Driver")   */
	char *driver_name;            /* File name - typically complete abs path. (ie "/usr/lib/libmyodbc3.so")   */
	char *pszSETUP;             /* File name - typically complete abs path. (ie "/usr/lib/libmyodbc3S.so")  */
} odbc_driver_t;

/*!
DSN fields.

This reflects what we can have in odbc.ini and also includes information
used during an SQLDriverConnect().
*/
typedef struct odbc_data_source_t
{
	char *drv_file_name;    /* As used in DSN; often the abs path to driver.        (ie "/usr/lib/libOPodbc3.so")           */
	char *dsn_name;               /* The name of our data source.                         (ie "test")                             */    
	char *driver_name;            /* Friendly driver name as used in DSN and connect str. (ie "OPSQL ODBC 3.51 Driver (32 bit)")  */
	char *dsn_desc;       /* General description or long name of DSN.                                                     */
	char *srv_name;            /* The hostname of the OPSQL server.                                                            */
	char *user_name;              /* The username used to connect to OPSQL. */
	char *passwd;          /* The password for the server user combination. */ 
	char *default_db;          /* The default database. */
	char *srv_port;              /* The TCP/IP port to use if SERVER is not localhost. */
	char *sock_name;            /* Unix socket file or Windows named pipe to connect to.                                        */ 
	char *stmt;              /* Statement that will be exec when connecting to OPSQL.                                        */ 
	char *option;            /* Options that specify how OPODBC should work.                                                  */

	//char *ssl_key;            /* pathname to SSL key file                                                                     */
	//char *ssl_cert;           /* pathname to SSL certificate file                                                             */
	//char *ssl_cert_auth_file;             /* pathname to SSL certificate authority file                                                   */
	//char *ssl_cert_auth_file_path;         /* pathname to a directory that contains SSL ceritificate authority files                       */
	//char *ssl_cipher;         /* pathname to a list of allowable g_name                                                      */
	//char *ssl_verify;         /* verify server certificate (see --ssl-verify-server-cert                                      */
	char *charset;           /* default charset to use for connection */
	char *read_timeout;       /* connection read timeout (see OPsql_options / OPSQL_OPT_READ_TIMEOUT */
	char *write_timeout;      /* connection write timeout (see OPsql_options / OPSQL_OPT_WRITE_TIMEOUT */

	odbc_data_source_mode_t      mode;      /* ConfigDSN mode or SQLDriverConnect mode.                                     */
	odbc_data_source_connect_t   connect;   /* SQLDriverConnect() using a DSN or a DRIVER to connect.                       */
	odbc_data_source_prompt_t    prompt;    /* SQLDriverConnect() kind of prompting (if any).                               */

	BOOL  save_file_dsn;         /* Flag specifying that SQLConnect was invoked as part of creation of a file DSN                */

} odbc_data_source_t;

/* odbc_data_source_t */
odbc_data_source_t * odbc_alloc_data_source(odbc_data_source_mode_t mode);

BOOL odbc_read_data_source(odbc_data_source_t *data_source, LPCSTR dsn_name);

void odbc_free_data_source(odbc_data_source_t *data_source);

void odbc_clear_data_source(odbc_data_source_t *data_source);

BOOL odbc_default_data_source(odbc_data_source_t *data_source);

BOOL odbc_get_driver_names(char *buffer, int n_buffer);

odbc_driver_t *odbc_alloc_driver();

BOOL odbc_read_driver(odbc_driver_t *driver, LPCSTR name, LPCSTR file_name);

void odbc_free_driver(odbc_driver_t *driver);

void odbc_clear_driver(odbc_driver_t *driver);

BOOL odbc_get_data_source_names(char *buffer, int n_buffer, UWORD scope);

BOOL odbc_read_data_source_str(odbc_data_source_t *data_source, 
									   odbc_delim_t delim, LPCSTR str);

BOOL odbc_read_data_source_str_val_term(odbc_delim_t delim, char ch);

BOOL odbc_read_data_source_str_term(odbc_delim_t delim, char *scan_char);

BOOL odbc_write_data_source_str(odbc_data_source_t *data_source, 
										odbc_delim_t delim, 
										char *str, 
										SQLSMALLINT max_len);

BOOL odbc_insert_str(char *str, LPCSTR str_in, SQLSMALLINT max_len, int *index);